﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Runtime.InteropServices;
using System.Text;
using System.Threading.Tasks;
using System.IO;

namespace Bamboo.Utils
{
    public class FileDiff
    {
        [DllImport("msvcrt.dll")]
        private static extern int memcmp(byte[] b1, byte[] b2, IntPtr count);

        public int BufferSize { get; private set; }
        byte[] buffer1;
        byte[] buffer2;

        public FileDiff(int bufferSize)
        {
            if (bufferSize < 4096) this.BufferSize = 4096;
            else if (bufferSize > 10485760) this.BufferSize = 10485760;
            else this.BufferSize = bufferSize;

            buffer1 = new byte[BufferSize];
            buffer2 = new byte[BufferSize];
        }

        public bool IsDiff(FileInfo file1, FileInfo file2)
        {
            if (file1.Length != file2.Length) //长度不同肯定不同
                return true;

            using (var fs1 = new FileStream(file1.FullName, FileMode.Open, FileAccess.Read))
            using (var fs2 = new FileStream(file2.FullName, FileMode.Open, FileAccess.Read))
            {
                int readSize1 = 0;
                int readSize2 = 0;
                long totalReadSize = 0;
                do
                {
                    readSize1 = fs1.Read(buffer1, 0, buffer1.Length);
                    readSize2 = fs2.Read(buffer2, 0, buffer2.Length);
                    if (readSize1 != readSize2) return true; //理论上不会走到这个分支，除非比较到一半文件被追加写入了
                    if (readSize1 == 0) return false;
                    //比较读到的内容
                    try
                    {
                        var ret = memcmp(buffer1, buffer2, new IntPtr(readSize1));
                        if (ret != 0) return true;
                    }
                    catch (Exception ex)
                    {
                        throw new Exception("memcmp错误，size=" + readSize1 + ", file1=" + file1.FullName + ", file2=" + file2.FullName + ", message=" + ex.Message, ex);
                    }
                    totalReadSize += readSize1;
                } while (totalReadSize < file1.Length);
                return false;
            }
        }
    }
}
